package com.config.handler;

import com.config.security.JwtTokenUtil;
import com.entity.sys.BaseEntity;
import com.service.sys.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Properties;


/**
 * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)   拦截执行器的方法
 * ParameterHandler (getParameterObject, setParameters)	拦截参数的处理
 * ResultSetHandler (handleResultSets, handleOutputParameters)	拦截结果集的处理
 * StatementHandler (prepare, parameterize, batch, update, query) 拦截Sql语法构建的处理
 *
 * @author Administrator
 */
@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Component
public class MybatisInterceptHandler implements Interceptor {

    @Resource
    private UserService userService;

    //token存放请求头的位置
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    //Bearer
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //获取到token, 通过token解析出用户名
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String authorization = request.getHeader(tokenHeader);
        if (null == authorization || !authorization.startsWith(tokenHead)) {
            return invocation.proceed();
        }
        String token = authorization.substring(tokenHead.length());
        String username = jwtTokenUtil.getUserNameFormToken(token);
        SqlCommandType sqlCommandType = null;
        log.info("mybatis拦截器获取到操作人：{}", username);
        for (Object arg : args) {
            // 一般第一个参数都是操作类型
            if (arg instanceof MappedStatement) {
                MappedStatement ms = (MappedStatement) arg;
                sqlCommandType = ms.getSqlCommandType();
                if (sqlCommandType == SqlCommandType.INSERT) {//如果是“增加”或“更新”操作，则继续进行默认操作信息赋值。否则，则退出
                    log.info("mybatis操作类型: {}", sqlCommandType);
                    continue;
                } else {
                    break;
                }
            }
            System.out.println("ARG类型：" + arg.getClass().getSuperclass().getName());
            //更新操作改到mybatisPlus填充字段，
            if (sqlCommandType == SqlCommandType.INSERT && arg instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) arg;
                baseEntity.setCreateTime(simpleDateFormat.format(new Date()));
                baseEntity.setUpdateTime(simpleDateFormat.format(new Date()));
                baseEntity.setCreateBy(username);
                baseEntity.setUpdateBy(username);
            }
        }
        return invocation.proceed();
    }


    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }

    /**
     * 获取第一个key的值
     *
     * @param map
     * @return
     */
    private static Object getFirstOrNull(Map<String, Object> map) {
        Object obj = null;
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            obj = entry.getValue();
            if (obj != null) {
                break;
            }
        }
        return obj;
    }

}



